#include <process.h>
#include <string.h>
#include <mm.h>

#define TASK_STACK_SIZE 512

struct list_head task_list_table[TASK_STATES];         /*   进程表   */
task_t* current;                               /*   当前运行的进程   */

/**
 * @brief task_init
 * 
 * @return uint32_t 
 */
void task_init(void)
{
    int i = TASK_STATES;
    while(i--) list_init(&task_list_table[i]);
}

uint32_t alloc_pid(void)
{
    static uint32_t pidCount = 0;
    return pidCount++;
}

int32_t alloc_stack(reg_t* pStack)
{
    *pStack = (char*)kmalloc(TASK_STACK_SIZE) + TASK_STACK_SIZE;
    return 0;
}

void thread_info_init(struct thread_info* ptf, uint8_t RPL)
{
    ptf->cs = seg_to_sel(SEG_CODE_LDT) | SA_TIL | RPL;
    ptf->ds = seg_to_sel(SEG_DATA_LDT) | SA_TIL | RPL;
    ptf->ss = ptf->fs = ptf->es = ptf->ds;
    ptf->gs = seg_to_sel(SEG_DATA_VIDEO) | RPL;
    ptf->eflags = EFLAGS_SYS_PSW;
}


/*   初始化 task_struct 结构体   */
int _register_task(uint32_t func, uint8_t DPL)
{
    struct seg_desc* gdtBase = gdt_base();
    task_t *task = kmalloc(sizeof(task_t));
    list_init(&task->task_list);
    list_add(&task->task_list, running_list);
    printk("task:%x, ldt base:%x,func %x \n", task, &task->ldt[0], func);

    task->dpl = DPL;
    task->pid = alloc_pid();
    task->priv = DPL;
    task->state = TASK_RUNNING;

    /*   初始化 ldt   */
    task->ldt[SEG_CODE_LDT] = gdtBase[SEG_CODE_SYS];
    task->ldt[SEG_DATA_LDT] = gdtBase[SEG_DATA_SYS];

    task->ldt[SEG_CODE_LDT].access = DA_CR | DPL;
    task->ldt[SEG_DATA_LDT].access = DA_DRW | DPL;

    /*   初始化寄存器选择子   */
    thread_info_init(&task->thread_info, DPL >> 5 & 0x03);

    /*   设置任务函数,堆栈   */
    task->thread_info.eip = func;
    return alloc_stack(&task->thread_info.esp);
}

/*   任务注册   */
int register_task(uint32_t func, uint8_t DPL)
{
    static uint32_t taskCount = 0;
    current = task_convert(running_list->next);
    // struct list_head *p = running_list->next;
    // while (p != running_list)
    // {
    //     printk("p:%x, current:%x, running list:%x\n", p,current, &running_list->next);
    //     p = p->next;
    // }
    
    set_task_ldt((uint32_t)&current->ldt[0], current->dpl);
    return  _register_task(func, DPL);
}

task_t* get_next_task()
{
    if(current->task_list.next == running_list)
        current = task_convert(current->task_list.next);
    return  (task_t*)task_convert(current->task_list.next);
}
/*   进程切换   */
void switch_to(void)
{
    current = get_next_task();
    set_task_ldt((uint32_t)&current->ldt[0], current->dpl);
}